extern int STRINGLENGTH;
extern const int MAX_JUNC_IN_READ;//If the full read can be mapped, dont scan for junctions ...

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  Find_Split_Junctions(OP* Junc_List,int Junc_List_Ptr,Hash & Junctions)
 *  Description:  Add junctions with the motif to the hash Junc_List. 
 * =====================================================================================
 */

void Find_Split_Junctions(OP* Junc_List,int Junc_List_Ptr,Hash & Junctions)
{
	OP JPair;
	for (int i=Junc_List_Ptr-1;i>=0;i--)
	{
		JPair.x=Junc_List[i].x;
		JPair.y=Junc_List[i].y;
		Junctions.Insert(JPair,Junc_List[i].Motif,10);
	}
}



/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  Juncs_In_Read(OP* Junc_List, int & Junc_List_Ptr, int Head_Start,int Head_Length,int Tail_Start, int Tail_Length)
 *  Description:  See if there are junction motifs in the read, and see if they are more than the allowed number..
 *		  Junctions that are found are added to Junc_List, and Junc_List_Ptr contains the current # of potential junctions
 * =====================================================================================
 */
int Juncs_In_Read(OP* Junc_List,int & Junc_List_Ptr,int Head_Start,int Head_Length,int Tail_Start, int Tail_Length)
{
	int Possible_Junc_Count=0;
	if(Head_Length && Tail_Length && Head_Length + Tail_Length >= STRINGLENGTH)
	{
		int Gap=Head_Length-(STRINGLENGTH-Tail_Length);
		int Motif=0;
		assert(Gap>=0);
		for (int i=-2;i<=Gap;i++) 
		{
			if(Motif=Scan_Plus_Motif(Head_Start+STRINGLENGTH-Tail_Length+i-1,Tail_Start+i))
			{
				Junc_List[Junc_List_Ptr].x=Head_Start+STRINGLENGTH-Tail_Length+i-1;
				Junc_List[Junc_List_Ptr].y=Tail_Start+i;
				Junc_List[Junc_List_Ptr++].Motif=Motif;
				if(++Possible_Junc_Count > MAX_JUNC_IN_READ) break;
			}
			else if(Motif=Scan_Minus_Motif(Head_Start+STRINGLENGTH-Tail_Length+i-1,Tail_Start+i))
			{
				Junc_List[Junc_List_Ptr].x=Head_Start+STRINGLENGTH-Tail_Length+i-1;
				Junc_List[Junc_List_Ptr].y=Tail_Start+i;
				Junc_List[Junc_List_Ptr++].Motif=Motif;
				if(++Possible_Junc_Count > MAX_JUNC_IN_READ) break;
			}
		}
	}
	return Possible_Junc_Count;
}



/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  Scan_Minus_Motif( x, y)
 *  Description:  Check for - strand motif in junction x,y
 * =====================================================================================
 */
int Scan_Minus_Motif(unsigned x,unsigned y)
{
	unsigned char DonorA= (unsigned char)(*(Original_Text+(Orig_Text+x+1)/4) << (((Orig_Text+x+1) % 4) * 2))>>6;
	unsigned char DonorB= (unsigned char)(*(Original_Text+(Orig_Text+x+2)/4) << (((Orig_Text+x+2) % 4) * 2))>>6;

	unsigned char AccA= (unsigned char)(*(Original_Text+(Orig_Text+y-2)/4) << (((Orig_Text+y-2) % 4) * 2))>>6;
	unsigned char AccB= (unsigned char)(*(Original_Text+(Orig_Text+y-1)/4) << (((Orig_Text+y-1) % 4) * 2))>>6;

	int Pairing =0;
	//------------------------------ Enumerate Donor sites ------------------------------------------------------
	// [GT-AG]-> ct - ac
	// [GC-AG]-> ct - gc
	// [AC-AT]-> at - gt
	if (DonorB == N_t)
	{
		if(DonorA == N_c)//CT
			Pairing = S_ct;
		else if (DonorA == N_a)//AT
			Pairing = S_at;
	}
	//------------------------------ Enumerate Acceptor sites ------------------------------------------------------
	//------------------------------ Enumerate Donor sites ------------------------------------------------------
	if (Pairing == S_ct)
	{
		Pairing=0;
		if (AccB == N_c)
		{
			if(AccA == N_a)//AC [CA-TC]
				Pairing= S_ct_ac;
			else if(AccA == N_g)//CG [CG-TC]
				Pairing= S_ct_gc;
		} 
	}
	else if (Pairing == S_at) 
	{
		if (AccA == N_g && AccB == N_t)//TG [TG-TA]
			Pairing = S_at_gt; 
		else
			Pairing = 0;
	}

	if (DUMP_ALL_JUNC && !Pairing) Pairing = S_dummy;//dont filter juncs...
	return Pairing;

}

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  Scan_Plus_Motif( x, y)
 *  Description:  Check for + strand motif in junction x,y
 * =====================================================================================
 */
int Scan_Plus_Motif(unsigned x,unsigned y)
{
	unsigned char DonorA= (unsigned char)(*(Original_Text+(Orig_Text+x+1)/4) << (((Orig_Text+x+1) % 4) * 2))>>6;
	unsigned char DonorB= (unsigned char)(*(Original_Text+(Orig_Text+x+2)/4) << (((Orig_Text+x+2) % 4) * 2))>>6;

	unsigned char AccA= (unsigned char)(*(Original_Text+(Orig_Text+y-2)/4) << (((Orig_Text+y-2) % 4) * 2))>>6;
	unsigned char AccB= (unsigned char)(*(Original_Text+(Orig_Text+y-1)/4) << (((Orig_Text+y-1) % 4) * 2))>>6;


	int Pairing =0;
	//------------------------------ Enumerate Acceptor sites ------------------------------------------------------
	if (AccA == N_a)
	{
		if(AccB == N_g)//AG -high chance case [GT-AG] or [GC - AG]
			Pairing = S_ag;
		else if (AccB == N_t)//AT - [AC-AT]
			Pairing = S_at;
	}
	//------------------------------ Enumerate Acceptor sites ------------------------------------------------------
	//------------------------------ Enumerate Donor sites ------------------------------------------------------
	if (Pairing == S_ag)
	{
		Pairing=0;
		if (DonorA == N_g)
		{
			if(DonorB == N_t)//GT [GT-AG]
				Pairing= S_gt_ag;
			else if(DonorB == N_c)//GC [GC-AG]
				Pairing= S_gc_ag;
		} 
	}
	else if (Pairing == S_at) 
	{
		if (DonorA == N_a && DonorB == N_c)//AC [AC-AT]
			Pairing = S_ac_at; 
		else
			Pairing = 0;
	}
	return Pairing;
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  De_Novo_Splice
 *  Description:  Predict splicings ...
 * =====================================================================================
 */
#define OVERHANG	10


int De_Novo_Splice(OP & Pair,JStat & JStat)
{

	int Pairing=Scan_Plus_Motif(Pair.x,Pair.y);
	JStat.Junc_Type=Pairing;
	return Pairing;
	//------------------------------ Enumerate Donor sites ------------------------------------------------------
}

int De_Novo_Splice_Rev(OP & Pair,JStat & JStat)
{

	int Pairing=Scan_Minus_Motif(Pair.x,Pair.y);
	JStat.Junc_Type=Pairing;
	return Pairing;
	//------------------------------ Enumerate Donor sites ------------------------------------------------------
}
/*void De_Novo_Splice(Island* Island_List,COVTYPE* Coverage,unsigned char* Possible_Splices,Offset_Record Current_Genome)
{

	Island* New_Node,*Current=Island_List;

	State TState;
	int Can_Acc_Top=0,Can_Don_Top=0;

	printf("\t+Starting De Novo splicing..\n");
	while(Current){if(Current->Status != DELETED && Current->Status != EXON ) break;Current=Current->Next;}//get next node.. Skip deleted or marked with exon

	while(Current)
	{
		unsigned Acc_Start=Current->Start-OVERHANG;
		//------------------------------ Enumerate Acceptor sites ------------------------------------------------------
		//Motif End is found...
		char Last=S_init;//initial state FSM
		Can_Acc_Top=0;
		TState.State=S_non;
		Can_Acceptor[Can_Acc_Top]=TState;

		for (unsigned i=Acc_Start;i<Acc_Start+OVERHANG;i++)
		{
			unsigned char Now= (unsigned char)(*(Original_Text+(Orig_Text+i)/4) << (((Orig_Text+i) % 4) * 2))>>6;
			if (Last == N_a)
			{
				switch(Now)
				{
					case N_g://AG -high chance case [GT-AG] or [GC - AG]
						TState.State=S_ag;TState.Location=i;
						TState.Score=1+Possible_Splices[i];//give high priority to AG motif..
						Can_Acceptor[Can_Acc_Top++]=TState;
						break;
					case N_t://AT - [AC-AT]
						TState.State=S_at;TState.Location=i;
						TState.Score=Possible_Splices[i]+0;
						Can_Acceptor[Can_Acc_Top++]=TState;
						break;
				}
			}
			Last=Now;

		}
		//------------------------------ Enumerate Acceptor sites ------------------------------------------------------
		//------------------------------ Enumerate Donor sites ------------------------------------------------------
		//Motif Start is found..
		unsigned Donor_Start=Current->End;
		Last=S_init;//initial state FSM
		Can_Don_Top=0;
		TState.State=S_non;
		Can_Donor[Can_Don_Top]=TState;

		for (unsigned i=Donor_Start-1;i<Donor_Start+OVERHANG;i++)
		{
			unsigned char Now= (unsigned char)(*(Original_Text+(Orig_Text+i)/4) << (((Orig_Text+i) % 4) * 2))>>6;
			if (Last == N_g)
			{
				switch(Now)
				{
					case N_t://GT [GT-AG]
						TState.State=S_gt;TState.Location=i-1;
						TState.Score=Possible_Splices[i-1]+1;//give high priority to GT motif..
						Can_Donor[Can_Don_Top++]=TState;
						break;
					case N_c://GC [GC-AG]
						TState.State=S_gc;TState.Location=i-1;
						TState.Score=Possible_Splices[i-1]+0;
						Can_Donor[Can_Don_Top++]=TState;
						break;
				}
			} 
			else if (Last == N_a)
			{
				switch(Now)
				{
					case N_c://AC [AC-AT]
						TState.State=S_ac;TState.Location=i-1;
						TState.Score=Possible_Splices[i-1]+0;
						Can_Donor[Can_Don_Top++]=TState;
						break;
				}
			}
			Last=Now;
		}
		//------------------------------ Enumerate Donor sites ------------------------------------------------------
		//find maximum score boundry..
		int Max_Location=Can_Acc_Top-1;
		if(Can_Acc_Top)//acceptor found
		{
			while (--Can_Acc_Top>=0)
			{
				if (Can_Acceptor[Can_Acc_Top].Score > Can_Acceptor[Max_Location].Score) Max_Location=Can_Acc_Top;
			}
			Current->Start=Can_Acceptor[Max_Location].Location+1;
			Current->Status += ACCEPTOR;
		}

		Max_Location=Can_Don_Top-1;
		if(Can_Don_Top)//acceptor found
		{
			while (--Can_Don_Top>=0)
			{
				if (Can_Donor[Can_Don_Top].Score >= Can_Donor[Max_Location].Score) Max_Location=Can_Don_Top;
			}

			Current->End=Can_Donor[Max_Location].Location;
			Current->Status += DONOR;
		}

		do {Current=Current->Next;} while(Current->Next && (Current->Start==UINT_MAX||Current->Status));//get next node..
	}
}*/




/*int Junc_In_Read_Minus(int Head_Start,int Head_Length,int Tail_Start, int Tail_Length)
{
	int Possible_Junc_Count=0;
	if(Head_Length && Tail_Length && Head_Length + Tail_Length >= STRINGLENGTH)
	{
		int Gap=Head_Length-(STRINGLENGTH-Tail_Length);
		assert(Gap>=0);
		for (int i=-2;i<=Gap;i++) 
		{
			if(Scan_Minus_Motif(Head_Start+STRINGLENGTH-Tail_Length+i-1,Tail_Start+i))
			{
				if(++Possible_Junc_Count > MAX_JUNC_IN_READ) break;
			}
		}
	}
	return Possible_Junc_Count;
}*/

